#include <iostream>
#include <string>

#include "dxyReflectClass.h"

using namespace dxy::reflect;

class A
{
public:
    std::string a = "a";
};

class B
{
public:
    std::string b = "b";
};

class Test : public DxyRelfectObject
{
public:
    Test() {printf("new Test\n");}
    ~Test() {printf("del Test\n");}

    void func()
    {
        if(m_a != nullptr)
        {
            m_a->a = "aaaa\n";
        }
    }

    void func2()
    {
        if(m_b != nullptr)
        {
            m_b->b += "1111\n";
        }
    }

    void func3(int i, int j)
    {
        std::cout << i + j << std::endl;
    }

    int func4()
    {
        return 666;
    }

    int func5(int x, int y)
    {
        return x + y;
    }

    void func6(const std::string & str)
    {
        std::cout << str << std::endl;
    }

    std::shared_ptr<A>      m_a = nullptr;
    std::shared_ptr<B>      m_b = nullptr;
};

CLASS_REGISTER(Test)
CLASS_FIELD_REGISTER(Test, m_a)
CLASS_FIELD_REGISTER(Test, m_b)
CLASS_FUNC_REGISTER(Test, func)
CLASS_FUNC_REGISTER(Test, func2)
CLASS_FUNC_REGISTER_ARGS(Test, func3, int, int)
CLASS_FUNC_REGISTER_RET(Test, func4, int)
CLASS_FUNC_REGISTER_ARGS_RET(Test, func5, int, int, int)
CLASS_FUNC_REGISTER_ARGS(Test, func6, const std::string)


int main(int, char**) 
{
    try
    {
        auto obj = DxyReflectClass::getInstance().getClassByName("Test");

        auto ma = std::make_shared<A>();
        auto mb = std::make_shared<B>();
        ma->a = "AAAAA";
        mb->b = "BBBBB";
        obj->set<std::shared_ptr<A>>("Test", "m_a", ma);
        obj->set<std::shared_ptr<B>>("Test", "m_b", mb);
        obj->call("Test", "func");
        obj->call("Test", "func2");
        obj->call("Test", "func3", 1, 2);
        int out = obj->call<int>("Test", "func4");
        int sum = obj->call<int, int, int>("Test", "func5", 3, 4);
        obj->get<std::shared_ptr<A>>("Test", "m_a", ma);
        obj->get<std::shared_ptr<B>>("Test", "m_b", mb);
        obj->call("Test", "func6", std::string("asd"));
        printf("%s", ma->a.c_str());
        printf("%s", mb->b.c_str());
        printf("%d\n", out);
        printf("%d\n", sum);

    }
    catch(const std::exception& e)
    {
        std::cerr << e.what() << '\n';
    }
}
